home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 January / EnigmA AMIGA RUN 33 (1999)(G.R. Edizioni)(IT)[!][issue 1999-01].iso / earcd / apus / boothack / old / bh980726.lha / bh980726-2 / linuxboot.c < prev    next >
C/C++ Source or Header  |  1997-02-22  |  49KB  |  1,811 lines

  1. /*
  2.  *  linux/arch/m68k/boot/amiga/linuxboot.c -- Generic routine to boot Linux/m68k
  3.  *                          on Amiga, used by both Amiboot and
  4.  *                          Amiga-Lilo.
  5.  *
  6.  *    Created 1996 by Geert Uytterhoeven
  7.  *
  8.  *
  9.  *  This file is based on the original bootstrap code (bootstrap.c):
  10.  *
  11.  *    Copyright (C) 1993, 1994 Hamish Macdonald
  12.  *                 Greg Harp
  13.  *
  14.  *            with work by Michael Rausch
  15.  *                 Geert Uytterhoeven
  16.  *                 Frank Neumann
  17.  *                 Andreas Schwab
  18.  *                 Jesper Skov
  19.  *
  20.  *
  21.  *  This file is subject to the terms and conditions of the GNU General Public
  22.  *  License.  See the file COPYING in the main directory of this archive
  23.  *  for more details.
  24.  *
  25.  *  History:
  26.  *    26 Feb 1998 Added support for booting APUS systems.
  27.  *    27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
  28.  *            interface version 1.0 (Geert)
  29.  *    03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
  30.  *            code for ataboot)
  31.  *    30 Dec 1996 Reverted the CPU detection to the old scheme
  32.  *            New boot parameter override scheme (Geert)
  33.  *      27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
  34.  *       9 Sep 1996 Rewritten option parsing
  35.  *            New parameter passing to linuxboot() (linuxboot_args)
  36.  *            (Geert)
  37.  *    18 Aug 1996 Updated for the new boot information structure (Geert)
  38.  *    10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
  39.  *            (Geert)
  40.  *    11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
  41.  *     7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
  42.  *            instead of 1M (Geert)
  43.  *    31 May 1994 Memory thrash problem solved (Geert)
  44.  *    11 May 1994 A3640 MapROM check (Geert)
  45.  */
  46.  
  47.  
  48. #ifndef __GNUC__
  49. #error GNU CC is required to compile this program
  50. #endif /* __GNUC__ */
  51.  
  52.  
  53. #define BOOTINFO_COMPAT_1_0    /* bootinfo interface version 1.0 compatible */
  54. /* support compressed kernels? */
  55. #define ZKERNEL
  56.  
  57. #include <stddef.h>
  58. #include <string.h>
  59. #include <errno.h>
  60. #include <sys/types.h>
  61.  
  62. #include <linux/a.out.h>
  63. #include <linux/elf.h>
  64. #include <linux/linkage.h>
  65. #include <asm/bootinfo.h>
  66. #include <asm/amigahw.h>
  67. #include <asm/page.h>
  68.  
  69. #include "linuxboot.h"
  70.  
  71.  
  72. #undef custom
  73. #define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
  74.  
  75. /* temporary stack size */
  76. #define TEMP_STACKSIZE    (256)
  77.  
  78. #define DEFAULT_BAUD    (9600)
  79.  
  80. extern char copyall, copyallend;
  81.  
  82. static struct exec kexec;
  83. static Elf32_Ehdr kexec_elf;
  84. static const struct linuxboot_args *linuxboot_args;
  85.  
  86. /* Bootinfo */
  87. struct amiga_bootinfo bi;
  88.  
  89. #ifdef BOOTINFO_COMPAT_1_0
  90. static struct compat_bootinfo compat_bootinfo;
  91. #endif /* BOOTINFO_COMPAT_1_0 */
  92.  
  93. #define MAX_BI_SIZE    (4096)
  94. static u_long bi_size;
  95. static union {
  96.     struct bi_record record;
  97.     u_char fake[MAX_BI_SIZE];
  98. } bi_union;
  99.  
  100. #define kernelname    linuxboot_args->kernelname
  101. #define ramdiskname    linuxboot_args->ramdiskname
  102. #define debugflag    linuxboot_args->debugflag
  103. #define keep_video    linuxboot_args->keep_video
  104. #define reset_boards    linuxboot_args->reset_boards
  105. #define baud        linuxboot_args->baud
  106.  
  107. #define apus_boot    linuxboot_args->apus_boot
  108. #define checksum    linuxboot_args->checksum
  109.  
  110. #define Puts        linuxboot_args->puts
  111. #define GetChar        linuxboot_args->getchar
  112. #define PutChar        linuxboot_args->putchar
  113. #define Printf        linuxboot_args->printf
  114. #define Open        linuxboot_args->open
  115. #define Seek        linuxboot_args->seek
  116. #define Read        linuxboot_args->read
  117. #define Close        linuxboot_args->close
  118. #define FileSize    linuxboot_args->filesize
  119. #define Sleep        linuxboot_args->sleep
  120.  
  121.     /*
  122.      *  Function Prototypes
  123.      */
  124.  
  125. static u_long get_chipset(void);
  126. static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu);
  127. static u_long get_model(u_long chipset);
  128. static int probe_resident(const char *name);
  129. static int probe_resource(const char *name);
  130. static int create_bootinfo(void);
  131. #ifdef BOOTINFO_COMPAT_1_0
  132. static int create_compat_bootinfo(void);
  133. #endif /* BOOTINFO_COMPAT_1_0 */
  134. static int add_bi_record(u_short tag, u_short size, const void *data);
  135. static int add_bi_string(u_short tag, const u_char *s);
  136. static int check_bootinfo_version(const char *memptr);
  137. static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
  138.              u_long start_mem, u_long mem_size, u_long rd_size,
  139.              u_long kernel_size) __attribute__ ((noreturn));
  140. asmlinkage u_long maprommed(void);
  141. asmlinkage u_long check346(void);
  142. #ifdef ZKERNEL
  143. static int load_zkernel(int fd);
  144. static int KRead(int fd, void *buf, int cnt);
  145. static int KSeek(int fd, int offset);
  146. static int KClose(int fd);
  147. #else
  148. #define KRead        Read
  149. #define KSeek        Seek
  150. #define KClose        Close
  151. #endif
  152.  
  153.  
  154.     /*
  155.      *    Reset functions for nasty Zorro boards
  156.      */
  157.  
  158. static void reset_rb3(const struct ConfigDev *cd);
  159. static void reset_piccolo(const struct ConfigDev *cd);
  160. static void reset_sd64(const struct ConfigDev *cd);
  161. static void reset_a2065(const struct ConfigDev *cd);
  162. static void reset_ariadne(const struct ConfigDev *cd);
  163. static void reset_hydra(const struct ConfigDev *cd);
  164. #if 0
  165. static void reset_a2060(const struct ConfigDev *cd);
  166. #endif
  167.  
  168. struct boardreset {
  169.     u_short manuf;
  170.     u_short prod;
  171.     const char *name;
  172.     void (*reset)(const struct ConfigDev *cd);
  173. };
  174.  
  175. static struct boardreset boardresetdb[] = {
  176.     { MANUF_HELFRICH1, PROD_RAINBOW3, "Rainbow 3", reset_rb3 },
  177.     { MANUF_HELFRICH2, PROD_PICCOLO_REG, "Piccolo", reset_piccolo },
  178.     { MANUF_HELFRICH2, PROD_SD64_REG, "SD64", reset_sd64 },
  179.     { MANUF_COMMODORE, PROD_A2065, "A2065", reset_a2065 },
  180.     { MANUF_VILLAGE_TRONIC, PROD_ARIADNE, "Ariadne", reset_ariadne },
  181.     { MANUF_HYDRA_SYSTEMS, PROD_AMIGANET, "Hydra", reset_hydra },
  182. #if 0
  183.     { MANUF_COMMODORE, PROD_A2060, "A2060", reset_a2060 },
  184. #endif
  185. };
  186. #define NUM_BOARDRESET    sizeof(boardresetdb)/sizeof(*boardresetdb)
  187.  
  188. static void (*boardresetfuncs[ZORRO_NUM_AUTO])(const struct ConfigDev *cd);
  189.  
  190.  
  191. const char *amiga_models[] = {
  192.     "Amiga 500", "Amiga 500+", "Amiga 600", "Amiga 1000", "Amiga 1200",
  193.     "Amiga 2000", "Amiga 2500", "Amiga 3000", "Amiga 3000T", "Amiga 3000+",
  194.     "Amiga 4000", "Amiga 4000T", "CDTV", "CD32", "Draco"
  195. };
  196. const u_long first_amiga_model = AMI_500;
  197. const u_long last_amiga_model = AMI_DRACO;
  198.  
  199.  
  200. #define MASK(model)    (1<<AMI_##model)
  201.  
  202. #define CLASS_A3000    (MASK(3000) | MASK(3000T))
  203. #define CLASS_A4000    (MASK(4000) | MASK(4000T))
  204. #define CLASS_ZKICK    (MASK(500) | MASK(1000) | MASK(2000) | MASK(2500))
  205.  
  206.  
  207.     /*
  208.      *    Boot the Linux/m68k Operating System
  209.      */
  210.  
  211. u_long linuxboot(const struct linuxboot_args *args)
  212. {
  213.     int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
  214.     int i, j;
  215.     const struct MemHeader *mnp;
  216.     struct ConfigDev *cdp = NULL;
  217.     char *memptr = NULL;
  218.     u_long *stack = NULL;
  219.     u_long fast_total, model_mask, startcodesize, start_mem, mem_size, rd_size;
  220.     u_long kernel_size;
  221.     u_int realbaud;
  222.     u_long memreq = 0, text_offset = 0;
  223.     Elf32_Phdr *kernel_phdrs = NULL;
  224.     void (*startfunc)(void);
  225.     u_short manuf;
  226.     u_char prod;
  227.     void *bi_ptr;
  228.     unsigned long* info;
  229.     struct ConfigDev *zdevs[ZORRO_NUM_AUTO];
  230.  
  231.     linuxboot_args = args;
  232.  
  233.     /* print the greet message */
  234.     Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
  235.     Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
  236.  
  237.     /* Note: Initial values in bi override detected values */
  238.     bi = args->bi;
  239.  
  240.     /* machine is Amiga */
  241.     bi.machtype = MACH_AMIGA;
  242.  
  243.     /* determine chipset */
  244.     if (!bi.chipset)
  245.     bi.chipset = get_chipset();
  246.  
  247.     /* determine CPU, FPU and MMU type */
  248.     if (!bi.cputype)
  249.     get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
  250.  
  251.     /* determine Amiga model */
  252.     if (!bi.model)
  253.     bi.model = get_model(bi.chipset);
  254.     model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
  255.  
  256.     /* Memory & AutoConfig based on 'unix_boot.c' by C= */
  257.  
  258.     /* find all of the autoconfig boards in the system */
  259.     if (!bi.num_autocon)
  260.     for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++)
  261.         if (bi.num_autocon < ZORRO_NUM_AUTO) {
  262.         zdevs[i] = cdp;
  263.         /* copy the contents of each structure into our boot info and
  264.            count this device */
  265.         memcpy(&bi.autocon[bi.num_autocon++], cdp,
  266.                sizeof(struct ConfigDev));
  267.         } else
  268.         Printf("Warning: too many AutoConfig devices. Ignoring device "
  269.                "at 0x%08lx\n", cdp->cd_BoardAddr);
  270.  
  271.     do_fast = bi.num_memory ? 0 : 1;
  272.     do_chip = bi.chip_size ? 0 : 1;
  273.     /* find out the memory in the system */
  274.     for (mnp = (struct MemHeader *)SysBase->MemList.lh_Head;
  275.      mnp->mh_Node.ln_Succ;
  276.      mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ) {
  277.     struct MemHeader mh;
  278.  
  279.     /* copy the information */
  280.     mh = *mnp;
  281.  
  282.     /* skip virtual memory */
  283.     if (!(mh.mh_Attributes & MEMF_PUBLIC))
  284.         continue;
  285.  
  286.     /* if we suspect that Kickstart is shadowed in an A3000,
  287.        modify the entry to show 512K more at the top of RAM
  288.        Check first for a MapROMmed A3640 board: overwriting the
  289.        Kickstart image causes an infinite lock-up on reboot! */
  290.     if ((mh.mh_Upper == (void *)0x07f80000) &&
  291.         (model_mask & (CLASS_A3000 | CLASS_A4000)))
  292.         if ((bi.cputype & CPU_68040) && Supervisor(maprommed))
  293.         Puts("A3640 MapROM detected.\n");
  294.         else if (model_mask & CLASS_A3000) {
  295.         mh.mh_Upper = (void *)0x08000000;
  296.         Puts("A3000 shadowed Kickstart detected.\n");
  297.         }
  298.  
  299.     /* if we suspect that Kickstart is zkicked,
  300.        modify the entry to show 512K more at the botton of RAM */
  301.     if ((mh.mh_Lower == (void *)0x00280020) &&
  302.         (model_mask & CLASS_ZKICK)) {
  303.         mh.mh_Lower = (void *)0x00200000;
  304.         Puts("ZKick detected.\n");
  305.     }
  306.  
  307.     /* mask the memory limit values */
  308.     mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
  309.     mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
  310.  
  311.     /* if fast memory */
  312.     if (do_fast && mh.mh_Attributes & MEMF_FAST) {
  313.         /* set the size value to the size of this block and mask off to a
  314.            256K increment */
  315.         u_long size = ((u_long)mh.mh_Upper-(u_long)mh.mh_Lower)&0xfffc0000;
  316.         if (size > 0)
  317.         if (bi.num_memory < NUM_MEMINFO) {
  318.             /* record the start and size */
  319.             bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
  320.             bi.memory[bi.num_memory].size = size;
  321.             /* count this block */
  322.             bi.num_memory++;
  323.         } else
  324.             Printf("Warning: too many memory blocks. Ignoring block "
  325.                    "of %ldK at 0x%08x\n", size>>10,
  326.                (u_long)mh.mh_Lower);
  327.     } else if (do_chip && mh.mh_Attributes & MEMF_CHIP)
  328.         /* if CHIP memory, record the size */
  329.         bi.chip_size = (u_long)mh.mh_Upper;
  330.     }
  331.  
  332.     /* get info from ExecBase */
  333.     if (!bi.vblank)
  334.     bi.vblank = SysBase->VBlankFrequency;
  335.     if (!bi.psfreq)
  336.     bi.psfreq = SysBase->PowerSupplyFrequency;
  337.     if (!bi.eclock)
  338.     bi.eclock = SysBase->ex_EClockFrequency;
  339.  
  340.     /* serial port */
  341.     if (!bi.serper) {
  342.     realbaud = baud ? baud : DEFAULT_BAUD;
  343.     bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
  344.     }
  345.  
  346.     /* display Amiga model */
  347.     if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
  348.     Printf("%s ", amiga_models[bi.model-first_amiga_model]);
  349.     else
  350.     Puts("Amiga ");
  351.  
  352.     /* display the CPU type */
  353.     Puts("CPU: ");
  354.     switch (bi.cputype) {
  355.     case CPU_68020:
  356.         Puts("68020 (Do you have an MMU?)");
  357.         break;
  358.     case CPU_68030:
  359.         Puts("68030");
  360.         break;
  361.     case CPU_68040:
  362.         Puts("68040");
  363.         break;
  364.     case CPU_68060:
  365.         Puts("68060");
  366.         break;
  367.     default:
  368.         Puts("Insufficient for Linux.  Aborting...\n");
  369.         Printf("SysBase->AttnFlags = 0x%08lx\n", SysBase->AttnFlags);
  370.         goto Fail;
  371.     }
  372.     switch (bi.fputype) {
  373.     case FPU_68881:
  374.         Puts(" with 68881 FPU");
  375.         break;
  376.     case FPU_68882:
  377.         Puts(" with 68882 FPU");
  378.         break;
  379.     case FPU_68040:
  380.     case FPU_68060:
  381.         Puts(" with internal FPU");
  382.         break;
  383.     default:
  384.         Puts(" without FPU");
  385.         break;
  386.     }
  387.  
  388.     /* display the chipset */
  389.     switch (bi.chipset) {
  390.     case CS_STONEAGE:
  391.         Puts(", old or unknown chipset");
  392.         break;
  393.     case CS_OCS:
  394.         Puts(", OCS");
  395.         break;
  396.     case CS_ECS:
  397.         Puts(", ECS");
  398.         break;
  399.     case CS_AGA:
  400.         Puts(", AGA chipset");
  401.         break;
  402.     }
  403.  
  404.     Puts("\n\n");
  405.  
  406.     /* display the command line */
  407.     Printf("Command line is '%s'\n", bi.command_line);
  408.  
  409.     /* display the clock statistics */
  410.     Printf("Vertical Blank Frequency: %ldHz\n", bi.vblank);
  411.     Printf("Power Supply Frequency: %ldHz\n", bi.psfreq);
  412.     Printf("EClock Frequency: %ldHz\n\n", bi.eclock);
  413.  
  414.     /* display autoconfig devices */
  415.     if (bi.num_autocon) {
  416.     Printf("Found %ld AutoConfig Device%s\n", bi.num_autocon,
  417.            bi.num_autocon > 1 ? "s" : "");
  418.     for (i = 0; i < bi.num_autocon; i++) {
  419.         Printf("Device %ld: addr = 0x%08lx", i,
  420.            (u_long)zdevs[i]->cd_BoardAddr);
  421.         boardresetfuncs[i] = NULL;
  422.         if (reset_boards) {
  423.         manuf = zdevs[i]->cd_Rom.er_Manufacturer;
  424.         prod = zdevs[i]->cd_Rom.er_Product;
  425.         for (j = 0; j < NUM_BOARDRESET; j++)
  426.             if ((manuf == boardresetdb[j].manuf) &&
  427.             (prod == boardresetdb[j].prod)) {
  428.             Printf(" [%s - will be reset at kernel boot time]",
  429.                    boardresetdb[j].name);
  430.             boardresetfuncs[i] = boardresetdb[j].reset;
  431.             break;
  432.             }
  433.         }
  434.         PutChar('\n');
  435.     }
  436.     } else
  437.     Puts("No AutoConfig Devices Found\n");
  438.  
  439.     /* display memory */
  440.     if (bi.num_memory) {
  441.     Printf("\nFound %ld Block%sof Memory\n", bi.num_memory,
  442.            bi.num_memory > 1 ? "s " : " ");
  443.     for (i = 0; i < bi.num_memory; i++)
  444.         Printf("Block %ld: 0x%08lx to 0x%08lx (%ldK)\n", i,
  445.            bi.memory[i].addr, bi.memory[i].addr+bi.memory[i].size,
  446.            bi.memory[i].size>>10);
  447.     } else {
  448.     Puts("No memory found?!  Aborting...\n");
  449.     goto Fail;
  450.     }
  451.  
  452.     /* display chip memory size */
  453.     Printf("%ldK of CHIP memory\n", bi.chip_size>>10);
  454.  
  455.     start_mem = bi.memory[0].addr;
  456.     mem_size = bi.memory[0].size;
  457.  
  458.     /* tell us where the kernel will go */
  459.     Printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
  460.  
  461.     /* verify that there is enough Chip RAM */
  462.     if (bi.chip_size < 512*1024) {
  463.     Puts("Not enough Chip RAM in this system.  Aborting...\n");
  464.     goto Fail;
  465.     }
  466.  
  467.     /* verify that there is enough Fast RAM */
  468.     for (fast_total = 0, i = 0; i < bi.num_memory; i++)
  469.     fast_total += bi.memory[i].size;
  470.     if (fast_total < 2*1024*1024) {
  471.     Puts("Not enough Fast RAM in this system.  Aborting...\n");
  472.     goto Fail;
  473.     }
  474.  
  475.     /* support for ramdisk */
  476.     if (ramdiskname) {
  477.     int size;
  478.  
  479.     if ((size = FileSize(ramdiskname)) == -1) {
  480.         Printf("Unable to find size of ramdisk file `%s'\n", ramdiskname);
  481.         goto Fail;
  482.     }
  483.     /* record ramdisk size */
  484.     bi.ramdisk.size = size;
  485.     } else
  486.     bi.ramdisk.size = 0;
  487.     rd_size = bi.ramdisk.size;
  488.     bi.ramdisk.addr = (u_long)start_mem+mem_size-rd_size;
  489.  
  490.     /* create the bootinfo structure */
  491.     if (!create_bootinfo())
  492.     goto Fail;
  493.  
  494.     /* open kernel executable and read exec header */
  495.     if ((kfd = Open(kernelname)) == -1) {
  496.     Printf("Unable to open kernel file `%s'\n", kernelname);
  497.     goto Fail;
  498.     }
  499.     if (KRead(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
  500.     Puts("Unable to read exec header from kernel file\n");
  501.     goto Fail;
  502.     }
  503.  
  504. #ifdef ZKERNEL
  505.     if (((unsigned char *)&kexec)[0] == 037 &&
  506.     (((unsigned char *)&kexec)[1] == 0213 ||
  507.      ((unsigned char *)&kexec)[1] == 0236)) {
  508.     /* That's a compressed kernel */
  509.     Puts("Kernel is compressed\n");
  510.     if (load_zkernel(kfd)) {
  511.         Puts("Decompression error -- aborting\n");
  512.         goto Fail;
  513.     }
  514.     }
  515. #endif
  516.  
  517.     switch (N_MAGIC(kexec)) {
  518.     case ZMAGIC:
  519.         if (debugflag)
  520.         Puts("\nLoading a.out (ZMAGIC) Linux/m68k kernel...\n");
  521.         text_offset = N_TXTOFF(kexec);
  522.         break;
  523.  
  524.     case QMAGIC:
  525.         if (debugflag)
  526.         Puts("\nLoading a.out (QMAGIC) Linux/m68k kernel...\n");
  527.         text_offset = sizeof(kexec);
  528.         /* the text size includes the exec header; remove this */
  529.         kexec.a_text -= sizeof(kexec);
  530.         break;
  531.  
  532.     default:
  533.         /* Try to parse it as an ELF header */
  534.         KSeek(kfd, 0);
  535.         if ((KRead(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
  536.          sizeof(kexec_elf)) &&
  537.          (memcmp(&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)) {
  538.         elf_kernel = 1;
  539.         if (debugflag)
  540.             Puts("\nLoading ELF Linux/m68k kernel...\n");
  541.         /* A few plausibility checks */
  542.         if ((kexec_elf.e_type != ET_EXEC) ||
  543.             (kexec_elf.e_machine != EM_PPC && apus_boot) ||
  544.             (kexec_elf.e_machine != EM_68K && !apus_boot) ||
  545.             (kexec_elf.e_version != EV_CURRENT)) {
  546.             Puts("Invalid ELF header contents in kernel\n");
  547.             Printf("machine : %d, type: %d, version: %d\n",
  548.              kexec_elf.e_machine, kexec_elf.e_type, kexec_elf.e_version);
  549.             goto Fail;
  550.         }
  551.         /* Load the program headers */
  552.         if (!(kernel_phdrs =
  553.               (Elf32_Phdr *)AllocMem(kexec_elf.e_phnum*sizeof(Elf32_Phdr),
  554.                          MEMF_FAST | MEMF_PUBLIC |
  555.                          MEMF_CLEAR))) {
  556.             Puts("Unable to allocate memory for program headers\n");
  557.             goto Fail;
  558.         }
  559.         KSeek(kfd, kexec_elf.e_phoff);
  560.         if (KRead(kfd, (void *)kernel_phdrs,
  561.              kexec_elf.e_phnum*sizeof(*kernel_phdrs)) !=
  562.             kexec_elf.e_phnum*sizeof(*kernel_phdrs)) {
  563.             Puts("Unable to read program headers from kernel file\n");
  564.             goto Fail;
  565.         }
  566.         break;
  567.         }
  568.         Printf("Wrong magic number 0x%08lx in kernel header\n",
  569.            N_MAGIC(kexec));
  570.         goto Fail;
  571.     }
  572.  
  573.     /* Load the kernel at one page after start of mem */
  574.     if (!apus_boot) {
  575.     start_mem += PAGE_SIZE;
  576.     mem_size -= PAGE_SIZE;
  577.     }
  578.  
  579.     /* Align bss size to multiple of four */
  580.     if (!elf_kernel)
  581.     kexec.a_bss = (kexec.a_bss+3) & ~3;
  582.  
  583.     /* calculate the total required amount of memory */
  584.     if (elf_kernel) {
  585.     u_long min_addr = 0xffffffff, max_addr = 0;
  586.     for (i = 0; i < kexec_elf.e_phnum; i++) {
  587.         if (min_addr > kernel_phdrs[i].p_vaddr)
  588.         min_addr = kernel_phdrs[i].p_vaddr;
  589.         if (max_addr < kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz)
  590.         max_addr = kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz;
  591.     }
  592.     /* This is needed for newer linkers that include the header in
  593.        the first segment.  */
  594.     if (apus_boot) {
  595.         /* Avoid ugly hacks further down. */
  596.         kernel_phdrs[0].p_vaddr = PAGE_SIZE;
  597.     } else if (min_addr == 0) {
  598.         min_addr = PAGE_SIZE;
  599.         kernel_phdrs[0].p_vaddr += PAGE_SIZE;
  600.         kernel_phdrs[0].p_offset += PAGE_SIZE;
  601.         kernel_phdrs[0].p_filesz -= PAGE_SIZE;
  602.         kernel_phdrs[0].p_memsz -= PAGE_SIZE;
  603.     }
  604.     kernel_size = max_addr-min_addr;
  605.     } else
  606.     kernel_size = kexec.a_text+kexec.a_data+kexec.a_bss;
  607.     memreq = kernel_size+bi_size+rd_size;
  608. #ifdef BOOTINFO_COMPAT_1_0
  609.     if (sizeof(compat_bootinfo) > bi_size)
  610.     memreq = kernel_size+sizeof(compat_bootinfo)+rd_size;
  611. #endif /* BOOTINFO_COMPAT_1_0 */
  612.     if (!(memptr = (char *)AllocMem(memreq, MEMF_FAST | MEMF_PUBLIC |
  613.                         MEMF_CLEAR))) {
  614.     Puts("Unable to allocate memory\n");
  615.     goto Fail;
  616.     }
  617.  
  618.     /* read the text and data segments from the kernel image */
  619.     if (elf_kernel)
  620.     for (i = 0; i < kexec_elf.e_phnum; i++) {
  621.         if (KSeek(kfd, kernel_phdrs[i].p_offset) == -1) {
  622.         Printf("Failed to seek to segment %ld\n", i);
  623.         goto Fail;
  624.         }
  625.         if (KRead(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
  626.               kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
  627.         Printf("Failed to read segment %ld\n", i);
  628.         goto Fail;
  629.         }
  630.     }
  631.     else {
  632.     if (KSeek(kfd, text_offset) == -1) {
  633.         Puts("Failed to seek to text\n");
  634.         goto Fail;
  635.     }
  636.     if (KRead(kfd, memptr, kexec.a_text) != kexec.a_text) {
  637.         Puts("Failed to read text\n");
  638.         goto Fail;
  639.     }
  640.     /* data follows immediately after text */
  641.     if (KRead(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
  642.         Puts("Failed to read data\n");
  643.         goto Fail;
  644.     }
  645.     }
  646.     KClose(kfd);
  647.     kfd = -1;
  648.  
  649.     /* Check kernel's bootinfo version */
  650.     switch (apus_boot ? BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION) :
  651.         check_bootinfo_version(memptr)) {
  652.     case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
  653.         bi_ptr = &bi_union.record;
  654.         break;
  655.  
  656. #ifdef BOOTINFO_COMPAT_1_0
  657.     case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
  658.         if (!create_compat_bootinfo())
  659.         goto Fail;
  660.         bi_ptr = &compat_bootinfo;
  661.         bi_size = sizeof(compat_bootinfo);
  662.         break;
  663. #endif /* BOOTINFO_COMPAT_1_0 */
  664.  
  665.     default:
  666.         goto Fail;
  667.     }
  668.  
  669.     /* copy the bootinfo to the end of the kernel image */
  670.     memcpy((void *)(memptr+kernel_size), bi_ptr, bi_size);
  671.  
  672.     if (ramdiskname) {
  673.     if ((rfd = Open(ramdiskname)) == -1) {
  674.         Printf("Unable to open ramdisk file `%s'\n", ramdiskname);
  675.         goto Fail;
  676.     }
  677.     if (Read(rfd, memptr+kernel_size+bi_size, rd_size) != rd_size) {
  678.         Puts("Failed to read ramdisk file\n");
  679.         goto Fail;
  680.     }
  681.     Close(rfd);
  682.     rfd = -1;
  683.     }
  684.  
  685.     /* allocate temporary chip ram stack */
  686.     if (!(stack = (u_long *)AllocMem(TEMP_STACKSIZE, MEMF_CHIP | MEMF_CLEAR))) {
  687.     Puts("Unable to allocate memory for stack\n");
  688.     goto Fail;
  689.     }
  690.  
  691.     /* allocate chip ram for copy of startup code */
  692.     startcodesize = ©allend-©all;
  693.     if (!(startfunc = (void (*)(void))AllocMem(startcodesize,
  694.                            MEMF_CHIP | MEMF_CLEAR))) {
  695.     Puts("Unable to allocate memory for startcode\n");
  696.     goto Fail;
  697.     }
  698.  
  699.     /* copy startup code to CHIP RAM */
  700.     memcpy(startfunc, ©all, startcodesize);
  701.  
  702.     if (debugflag) {
  703.     if (bi.ramdisk.size)
  704.         Printf("RAM disk at 0x%08lx, size is %ldK\n",
  705.            (u_long)memptr+kernel_size, bi.ramdisk.size>>10);
  706.  
  707.     if (elf_kernel) {
  708.         PutChar('\n');
  709.         for (i = 0; i < kexec_elf.e_phnum; i++)
  710.         Printf("Kernel segment %ld at 0x%08lx, size %ld\n", i,
  711.                start_mem+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
  712.                kernel_phdrs[i].p_memsz);
  713.         Printf("Boot info        at 0x%08lx\n", start_mem+kernel_size);
  714.     } else {
  715.         Printf("\nKernel text at 0x%08lx, code size 0x%08lx\n", start_mem,
  716.            kexec.a_text);
  717.         Printf("Kernel data at 0x%08lx, data size 0x%08lx\n",
  718.            start_mem+kexec.a_text, kexec.a_data);
  719.         Printf("Kernel bss  at 0x%08lx, bss  size 0x%08lx\n",
  720.            start_mem+kexec.a_text+kexec.a_data, kexec.a_bss);
  721.         Printf("Boot info   at 0x%08lx\n", start_mem+kernel_size);
  722.     }
  723.     Printf("\nKernel entry is 0x%08lx\n", elf_kernel ? kexec_elf.e_entry :
  724.                                kexec.a_entry);
  725.  
  726.     Printf("ramdisk dest top is 0x%08lx\n", start_mem+mem_size);
  727.     Printf("ramdisk lower limit is 0x%08lx\n",
  728.            (u_long)(memptr+kernel_size));
  729.     Printf("ramdisk src top is 0x%08lx\n",
  730.            (u_long)(memptr+kernel_size)+rd_size);
  731.  
  732.     Puts("\nType a key to continue the Linux/m68k boot...");
  733.     GetChar();
  734.     PutChar('\n');
  735.     }
  736.  
  737.     /* wait for things to settle down */
  738.     Sleep(1000000);
  739.  
  740.     /* turn off caches */
  741.     CacheControl(0, ~0);
  742.     
  743.     if (!keep_video)
  744.     /* set graphics mode to a nice normal one */
  745.     LoadView(NULL);
  746.  
  747.     /* reset nasty Zorro boards */
  748.     if (reset_boards)
  749.     for (i = 0; i < bi.num_autocon; i++)
  750.         if (boardresetfuncs[i])
  751.             boardresetfuncs[i](zdevs[i]);
  752.  
  753. #define CHIP_PTR (0xfff00)
  754. #define INFO_SIZE (0x2000 + 0x0100)
  755.     if (apus_boot) {
  756.         /* Let the PowerPC handle the actual kernel start */
  757.     
  758.         /* Store some relevant information about the kernel image
  759.          * and RAM disk at *CHIP_PTR.
  760.          */
  761.         void* elfObject;
  762.         unsigned long boot_msg;
  763.         
  764.         /* Make sure the CHIP_PTR will not be destroyed. */
  765.         if (!AllocAbs (0x10, CHIP_PTR)){
  766.             Puts("Unable to allocate CHIP memory at 0xfff00.\n"
  767.                  "Try booting with a smaller resolution.\n");
  768.         }
  769.         
  770.         if (!(boot_msg = (unsigned long) AllocMem (0x200, 
  771.                                                    MEMF_REVERSE 
  772.                                                    | MEMF_CHIP 
  773.                                                    | MEMF_CLEAR))){
  774.                                                    
  775.             Puts("Unable to allocate CHIP memory for boot message\n");
  776.             goto Fail;
  777.         }
  778.  
  779.         if (!(info = (unsigned long*) AllocMem (INFO_SIZE, 
  780.                                                 MEMF_CHIP | MEMF_CLEAR))){
  781.             Puts("Unable to allocate CHIP memory for info table and"
  782.                  " reloc code\n");
  783.             goto Fail;
  784.         }        
  785.  
  786.         /* Leave the pointer in chip mem at address CHIP_PTR. */
  787.         *((unsigned long*) CHIP_PTR) = (unsigned long) info;
  788.         info[0] = (unsigned long) (memptr+kernel_phdrs[0].p_vaddr-PAGE_SIZE);
  789.         info[1] = start_mem;
  790.         info[2] = kernel_size;
  791.         info[3] = bi_size;
  792.         info[4] = rd_size;
  793.         info[5] = mem_size;
  794.         info[6] = boot_msg + 0x100;
  795.  
  796.         /* Calculate a simple kernel checksum. */
  797.         if (checksum)
  798.         {
  799.             int i = (info[2] + info[3]) / 4;
  800.             unsigned char* k_p = (unsigned char*) info[0];
  801.             unsigned long kcs = 0;
  802.             
  803.             while (i--)
  804.             {
  805.                 unsigned long w = 0;
  806.                 
  807.                 w |= *k_p++;
  808.                 w <<= 8;
  809.                 w |= *k_p++;
  810.                 w <<= 8;
  811.                 w |= *k_p++;
  812.                 w <<= 8;
  813.                 w |= *k_p++;
  814.  
  815.                 
  816.                 kcs = kcs ^ i;
  817.                 kcs = kcs ^ w;
  818.             }
  819.             info[7] = kcs;
  820.         }
  821.         else
  822.         {
  823.             info[7] = 0;
  824.         }
  825.         
  826.         elfObject = (void*) PPCLoadObject("ram:ppc_boot");
  827.         PPCCreateTask(elfObject, 0);
  828.     }
  829.  
  830.     /* Go into supervisor state */
  831.     SuperState();
  832.  
  833.     /* Turn off interrupts. */
  834.     Disable();
  835.  
  836.     /* Turn off all DMA */
  837.     custom.dmacon = DMAF_ALL | DMAF_MASTER;
  838.     
  839.     if (apus_boot) {
  840.         /* LPSTOP cannot be used on the 68060. Apparently the 
  841.            CyberStorm bus design cannot cope with it.*/
  842.         /* Just let the 68k hang for now. */
  843.         __asm __volatile ("stop    #0x2700 \n\t");
  844.     }
  845.  
  846.     /* turn off any mmu translation */
  847.     disable_mmu();
  848.  
  849.     /* execute the copy-and-go code (from CHIP RAM) */
  850.     start_kernel(startfunc, (char *)stack+TEMP_STACKSIZE, memptr, start_mem,
  851.          mem_size, rd_size, kernel_size);
  852.  
  853.     /* Clean up and exit in case of a failure */
  854. Fail:
  855.     if (kfd != -1)
  856.     KClose(kfd);
  857.     if (rfd != -1)
  858.     Close(rfd);
  859.     if (info)
  860.     FreeMem((void *) info, INFO_SIZE);
  861.     if (memptr)
  862.     FreeMem((void *)memptr, memreq);
  863.     if (stack)
  864.     FreeMem((void *)stack, TEMP_STACKSIZE);
  865.     if (kernel_phdrs)
  866.     FreeMem((void *)kernel_phdrs, kexec_elf.e_phnum*sizeof(Elf32_Phdr));
  867.     return(FALSE);
  868. }
  869.  
  870.  
  871.     /*
  872.      *    Determine the Chipset
  873.      */
  874.  
  875. static u_long get_chipset(void)
  876. {
  877.     u_char cs;
  878.     u_long chipset;
  879.  
  880.     if (GfxBase->Version >= 39)
  881.     cs = SetChipRev(SETCHIPREV_BEST);
  882.     else
  883.     cs = GfxBase->ChipRevBits0;
  884.     if ((cs & GFXG_AGA) == GFXG_AGA)
  885.     chipset = CS_AGA;
  886.     else if ((cs & GFXG_ECS) == GFXG_ECS)
  887.     chipset = CS_ECS;
  888.     else if ((cs & GFXG_OCS) == GFXG_OCS)
  889.     chipset = CS_OCS;
  890.     else
  891.     chipset = CS_STONEAGE;
  892.     return(chipset);
  893. }
  894.  
  895.  
  896.     /*
  897.      *    Determine the CPU Type
  898.      */
  899.  
  900. static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
  901. {
  902.     *cpu = *fpu = 0;
  903.  
  904.     if (SysBase->AttnFlags & AFF_68060)
  905.     *cpu = CPU_68060;
  906.     else if (SysBase->AttnFlags & AFF_68040)
  907.     *cpu = CPU_68040;
  908.     else if (SysBase->AttnFlags & AFF_68030)
  909.     *cpu = CPU_68030;
  910.     else if (SysBase->AttnFlags & AFF_68020)
  911.     *cpu = CPU_68020;
  912.  
  913.     if (*cpu == CPU_68040 || *cpu == CPU_68060) {
  914.     if (SysBase->AttnFlags & AFF_FPU40)
  915.         *fpu = *cpu;
  916.     } else if (SysBase->AttnFlags & AFF_68882)
  917.     *fpu = FPU_68882;
  918.     else if (SysBase->AttnFlags & AFF_68881)
  919.     *fpu = FPU_68881;
  920.  
  921.     *mmu = *cpu;
  922. }
  923.  
  924.     /*
  925.      *    Determine the Amiga Model
  926.      */
  927.  
  928. static u_long get_model(u_long chipset)
  929. {
  930.     u_long model = AMI_UNKNOWN;
  931.  
  932.     if (debugflag)
  933.     Puts("Amiga model identification:\n");
  934.     if (probe_resource("draco.resource"))
  935.     model = AMI_DRACO;
  936.     else {
  937.     if (debugflag)
  938.         Puts("    Chipset: ");
  939.     switch (chipset) {
  940.         case CS_STONEAGE:
  941.         if (debugflag)
  942.             Puts("Old or unknown\n");
  943.         goto OCS;
  944.         break;
  945.  
  946.         case CS_OCS:
  947.         if (debugflag)
  948.             Puts("OCS\n");
  949. OCS:        if (probe_resident("cd.device"))
  950.             model = AMI_CDTV;
  951.         else
  952.             /* let's call it an A2000 (may be A500, A1000, A2500) */
  953.             model = AMI_2000;
  954.         break;
  955.  
  956.         case CS_ECS:
  957.         if (debugflag)
  958.             Puts("ECS\n");
  959.         if (probe_resident("Magic 36.7") ||
  960.             probe_resident("kickad 36.57") ||
  961.             probe_resident("A3000 Bonus") ||
  962.             probe_resident("A3000 bonus"))
  963.             /* let's call it an A3000 (may be A3000T) */
  964.             model = AMI_3000;
  965.         else if (probe_resource("card.resource"))
  966.             model = AMI_600;
  967.         else
  968.             /* let's call it an A2000 (may be A500[+], A1000, A2500) */
  969.             model = AMI_2000;
  970.         break;
  971.  
  972.         case CS_AGA:
  973.         if (debugflag)
  974.             Puts("AGA\n");
  975.         if (probe_resident("A1000 Bonus") ||
  976.             probe_resident("A4000 bonus"))
  977.             model = probe_resident("NCR scsi.device") ? AMI_4000T :
  978.                                 AMI_4000;
  979.         else if (probe_resource("card.resource"))
  980.             model = AMI_1200;
  981.         else if (probe_resident("cd.device"))
  982.             model = AMI_CD32;
  983.         else
  984.             model = AMI_3000PLUS;
  985.         break;
  986.     }
  987.     }
  988.     if (debugflag) {
  989.     Puts("\nType a key to continue...");
  990.     GetChar();
  991.     Puts("\n\n");
  992.     }
  993.     return(model);
  994. }
  995.  
  996.  
  997.     /*
  998.      *    Probe for a Resident Modules
  999.      */
  1000.  
  1001. static int probe_resident(const char *name)
  1002. {
  1003.     const struct Resident *res;
  1004.  
  1005.     if (debugflag)
  1006.     Printf("    Module `%s': ", name);
  1007.     res = FindResident(name);
  1008.     if (debugflag)
  1009.     if (res)
  1010.         Printf("0x%08lx\n", res);
  1011.     else
  1012.         Puts("not present\n");
  1013.     return(res ? TRUE : FALSE);
  1014. }
  1015.  
  1016.  
  1017.     /*
  1018.      *    Probe for an available Resource
  1019.      */
  1020.  
  1021. static int probe_resource(const char *name)
  1022. {
  1023.     const void *res;
  1024.  
  1025.     if (debugflag)
  1026.     Printf("    Resource `%s': ", name);
  1027.     res = OpenResource(name);
  1028.     if (debugflag)
  1029.     if (res)
  1030.         Printf("0x%08lx\n", res);
  1031.     else
  1032.         Puts("not present\n");
  1033.     return(res ? TRUE : FALSE);
  1034. }
  1035.  
  1036.  
  1037.     /*
  1038.      *  Create the Bootinfo structure
  1039.      */
  1040.  
  1041. static int create_bootinfo(void)
  1042. {
  1043.     int i;
  1044.     struct bi_record *record;
  1045.  
  1046.     /* Initialization */
  1047.     bi_size = 0;
  1048.  
  1049.     /* Generic tags */
  1050.     if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
  1051.     return(0);
  1052.     if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
  1053.     return(0);
  1054.     if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
  1055.     return(0);
  1056.     if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
  1057.     return(0);
  1058.     for (i = 0; i < bi.num_memory; i++)
  1059.     if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
  1060.         return(0);
  1061.     if (bi.ramdisk.size)
  1062.     if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
  1063.         return(0);
  1064.     if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
  1065.     return(0);
  1066.  
  1067.     /* Amiga tags */
  1068.     if (!add_bi_record(BI_AMIGA_MODEL, sizeof(bi.model), &bi.model))
  1069.     return(0);
  1070.     for (i = 0; i < bi.num_autocon; i++)
  1071.     if (!add_bi_record(BI_AMIGA_AUTOCON, sizeof(bi.autocon[i]),
  1072.                 &bi.autocon[i]))
  1073.         return(0);
  1074.     if (!add_bi_record(BI_AMIGA_CHIP_SIZE, sizeof(bi.chip_size), &bi.chip_size))
  1075.     return(0);
  1076.     if (!add_bi_record(BI_AMIGA_VBLANK, sizeof(bi.vblank), &bi.vblank))
  1077.     return(0);
  1078.     if (!add_bi_record(BI_AMIGA_PSFREQ, sizeof(bi.psfreq), &bi.psfreq))
  1079.     return(0);
  1080.     if (!add_bi_record(BI_AMIGA_ECLOCK, sizeof(bi.eclock), &bi.eclock))
  1081.     return(0);
  1082.     if (!add_bi_record(BI_AMIGA_CHIPSET, sizeof(bi.chipset), &bi.chipset))
  1083.     return(0);
  1084.     if (!add_bi_record(BI_AMIGA_SERPER, sizeof(bi.serper), &bi.serper))
  1085.     return(0);
  1086.  
  1087.     /* Trailer */
  1088.     record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
  1089.     record->tag = BI_LAST;
  1090.     bi_size += sizeof(bi_union.record.tag);
  1091.  
  1092.     return(1);
  1093. }
  1094.  
  1095.  
  1096.     /*
  1097.      *  Add a Record to the Bootinfo Structure
  1098.      */
  1099.  
  1100. static int add_bi_record(u_short tag, u_short size, const void *data)
  1101. {
  1102.     struct bi_record *record;
  1103.     u_int size2;
  1104.  
  1105.     size2 = (sizeof(struct bi_record)+size+3)&-4;
  1106.     if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
  1107.     Puts("Can't add bootinfo record. Ask a wizard to enlarge me.\n");
  1108.     return(0);
  1109.     }
  1110.     record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
  1111.     record->tag = tag;
  1112.     record->size = size2;
  1113.     memcpy(record->data, data, size);
  1114.     bi_size += size2;
  1115.     return(1);
  1116. }
  1117.  
  1118.  
  1119.     /*
  1120.      *  Add a String Record to the Bootinfo Structure
  1121.      */
  1122.  
  1123. static int add_bi_string(u_short tag, const u_char *s)
  1124. {
  1125.     return(add_bi_record(tag, strlen(s)+1, (void *)s));
  1126. }
  1127.  
  1128.  
  1129. #ifdef BOOTINFO_COMPAT_1_0
  1130.  
  1131.     /*
  1132.      *  Create the Bootinfo structure for backwards compatibility mode
  1133.      */
  1134.  
  1135. static int create_compat_bootinfo(void)
  1136. {
  1137.     u_int i;
  1138.  
  1139.     compat_bootinfo.machtype = bi.machtype;
  1140.     if (bi.cputype & CPU_68020)
  1141.     compat_bootinfo.cputype = COMPAT_CPU_68020;
  1142.     else if (bi.cputype & CPU_68030)
  1143.     compat_bootinfo.cputype = COMPAT_CPU_68030;
  1144.     else if (bi.cputype & CPU_68040)
  1145.     compat_bootinfo.cputype = COMPAT_CPU_68040;
  1146.     else if (bi.cputype & CPU_68060)
  1147.     compat_bootinfo.cputype = COMPAT_CPU_68060;
  1148.     else {
  1149.     Printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
  1150.     return(0);
  1151.     }
  1152.     if (bi.fputype & FPU_68881)
  1153.     compat_bootinfo.cputype |= COMPAT_FPU_68881;
  1154.     else if (bi.fputype & FPU_68882)
  1155.     compat_bootinfo.cputype |= COMPAT_FPU_68882;
  1156.     else if (bi.fputype & FPU_68040)
  1157.     compat_bootinfo.cputype |= COMPAT_FPU_68040;
  1158.     else if (bi.fputype & FPU_68060)
  1159.     compat_bootinfo.cputype |= COMPAT_FPU_68060;
  1160.     else if (bi.fputype) {
  1161.     Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
  1162.     return(0);
  1163.     }
  1164.     compat_bootinfo.num_memory = bi.num_memory;
  1165.     if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
  1166.     Printf("Warning: using only %ld blocks of memory\n",
  1167.            COMPAT_NUM_MEMINFO);
  1168.     compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
  1169.     }
  1170.     for (i = 0; i < compat_bootinfo.num_memory; i++) {
  1171.     compat_bootinfo.memory[i].addr = bi.memory[i].addr;
  1172.     compat_bootinfo.memory[i].size = bi.memory[i].size;
  1173.     }
  1174.     if (bi.ramdisk.size) {
  1175.     compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
  1176.     compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
  1177.     } else {
  1178.     compat_bootinfo.ramdisk_size = 0;
  1179.     compat_bootinfo.ramdisk_addr = 0;
  1180.     }
  1181.     strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
  1182.     compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
  1183.  
  1184.     compat_bootinfo.bi_amiga.model = bi.model;
  1185.     compat_bootinfo.bi_amiga.num_autocon = bi.num_autocon;
  1186.     if (compat_bootinfo.bi_amiga.num_autocon > COMPAT_NUM_AUTO) {
  1187.     Printf("Warning: using only %ld AutoConfig devices\n",
  1188.            COMPAT_NUM_AUTO);
  1189.     compat_bootinfo.bi_amiga.num_autocon = COMPAT_NUM_AUTO;
  1190.     }
  1191.     for (i = 0; i < compat_bootinfo.bi_amiga.num_autocon; i++)
  1192.     compat_bootinfo.bi_amiga.autocon[i] = bi.autocon[i];
  1193.     compat_bootinfo.bi_amiga.chip_size = bi.chip_size;
  1194.     compat_bootinfo.bi_amiga.vblank = bi.vblank;
  1195.     compat_bootinfo.bi_amiga.psfreq = bi.psfreq;
  1196.     compat_bootinfo.bi_amiga.eclock = bi.eclock;
  1197.     compat_bootinfo.bi_amiga.chipset = bi.chipset;
  1198.     compat_bootinfo.bi_amiga.hw_present = 0;
  1199.     return(1);
  1200. }
  1201. #endif /* BOOTINFO_COMPAT_1_0 */
  1202.  
  1203.  
  1204.     /*
  1205.      *  Compare the Bootstrap and Kernel Versions
  1206.      */
  1207.  
  1208. static int check_bootinfo_version(const char *memptr)
  1209. {
  1210.     const struct bootversion *bv = (struct bootversion *)memptr;
  1211.     unsigned long version = 0;
  1212.     int i, kernel_major, kernel_minor, boots_major, boots_minor;
  1213.  
  1214.     if (bv->magic == BOOTINFOV_MAGIC)
  1215.     for (i = 0; bv->machversions[i].machtype != 0; ++i)
  1216.         if (bv->machversions[i].machtype == MACH_AMIGA) {
  1217.         version = bv->machversions[i].version;
  1218.         break;
  1219.         }
  1220.     if (!version)
  1221.     Puts("Kernel has no bootinfo version info, assuming 0.0\n");
  1222.  
  1223.     kernel_major = BI_VERSION_MAJOR(version);
  1224.     kernel_minor = BI_VERSION_MINOR(version);
  1225.     boots_major  = BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION);
  1226.     boots_minor  = BI_VERSION_MINOR(AMIGA_BOOTI_VERSION);
  1227.     Printf("Bootstrap's bootinfo version: %ld.%ld\n", boots_major,
  1228.        boots_minor);
  1229.     Printf("Kernel's bootinfo version   : %ld.%ld\n", kernel_major,
  1230.        kernel_minor);
  1231.  
  1232.     switch (kernel_major) {
  1233.     case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
  1234.         if (kernel_minor > boots_minor) {
  1235.         Puts("Warning: Bootinfo version of bootstrap and kernel "
  1236.                "differ!\n");
  1237.         Puts("         Certain features may not work.\n");
  1238.         }
  1239.         break;
  1240.  
  1241. #ifdef BOOTINFO_COMPAT_1_0
  1242.     case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
  1243.         Puts("(using backwards compatibility mode)\n");
  1244.         break;
  1245. #endif /* BOOTINFO_COMPAT_1_0 */
  1246.  
  1247.     default:
  1248.         Printf("\nThis bootstrap is too %s for this kernel!\n",
  1249.            boots_major < kernel_major ? "old" : "new");
  1250.         return(0);
  1251.     }
  1252.     return(kernel_major);
  1253. }
  1254.  
  1255.  
  1256.     /*
  1257.      *    Call the copy-and-go-code
  1258.      */
  1259.  
  1260. static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
  1261.              u_long start_mem, u_long mem_size, u_long rd_size,
  1262.              u_long kernel_size)
  1263. {
  1264.     register void (*a0)() __asm("a0") = startfunc;
  1265.     register char *a2 __asm("a2") = stackp;
  1266.     register char *a3 __asm("a3") = memptr;
  1267.     register u_long a4 __asm("a4") = start_mem;
  1268.     register u_long d0 __asm("d0") = mem_size;
  1269.     register u_long d1 __asm("d1") = rd_size;
  1270.     register u_long d2 __asm("d2") = kernel_size;
  1271.     register u_long d3 __asm("d3") = bi_size;
  1272.  
  1273.     __asm __volatile ("movel a2,sp;"
  1274.               "jmp a0@"
  1275.               : /* no outputs */
  1276.               : "r" (a0), "r" (a2), "r" (a3), "r" (a4), "r" (d0),
  1277.             "r" (d1), "r" (d2), "r" (d3)
  1278.               /* no return */);
  1279.     /* fake a noreturn */
  1280.     for (;;);
  1281. }
  1282.  
  1283.  
  1284.     /*
  1285.      *    This assembler code is copied to chip ram, and then executed.
  1286.      *    It copies the kernel to it's final resting place.
  1287.      *
  1288.      *    It is called with:
  1289.      *
  1290.      *        a3 = memptr
  1291.      *        a4 = start_mem
  1292.      *        d0 = mem_size
  1293.      *        d1 = rd_size
  1294.      *        d2 = kernel_size
  1295.      *        d3 = bi_size
  1296.      */
  1297.  
  1298. asm(".text\n"
  1299. ALIGN_STR "\n"
  1300. SYMBOL_NAME_STR(_copyall) ":
  1301.                 | /* copy kernel text and data */
  1302.     movel    a3,a0        | src = (u_long *)memptr;
  1303.     movel    a0,a2        | limit = (u_long *)(memptr+kernel_size);
  1304.     addl    d2,a2
  1305.     movel    a4,a1        | dest = (u_long *)start_mem;
  1306. 1:    cmpl    a0,a2
  1307.     jeq    2f        | while (src < limit)
  1308.     moveb    a0@+,a1@+    |  *dest++ = *src++;
  1309.     jra    1b
  1310. 2:
  1311.                 | /* copy bootinfo to end of bss */
  1312.     movel    a3,a0        | src = (u_long *)(memptr+kernel_size);
  1313.     addl    d2,a0        | dest = end of bss (already in a1)
  1314.     movel    d3,d7        | count = bi_size
  1315.     subql    #1,d7
  1316. 1:    moveb    a0@+,a1@+    | while (--count > -1)
  1317.     dbra    d7,1b        |     *dest++ = *src++
  1318.  
  1319.                 | /* copy the ramdisk to the top of memory */
  1320.                 | /* (from back to front) */
  1321.     movel    a4,a1        | dest = (u_long *)(start_mem+mem_size);
  1322.     addl    d0,a1
  1323.     movel    a3,a2        | limit = (u_long *)(memptr+kernel_size +
  1324.     addl    d2,a2        |             bi_size);
  1325.     addl    d3,a2
  1326.     movel    a2,a0        | src = (u_long *)((u_long)limit+rd_size);
  1327.     addl    d1,a0
  1328. 1:    cmpl    a0,a2
  1329.     beqs    2f        | while (src > limit)
  1330.     moveb    a0@-,a1@-    |     *--dest = *--src;
  1331.     bras    1b
  1332. 2:
  1333.                 | /* jump to start of kernel */
  1334.     movel    a4,a0        | jump_to (start_mem);
  1335.     jmp    a0@
  1336. "
  1337. SYMBOL_NAME_STR(_copyallend) ":
  1338. ");
  1339.  
  1340.  
  1341.     /*
  1342.      *    Test for a MapROMmed A3640 Board
  1343.      */
  1344.  
  1345. asm(".text\n"
  1346. ALIGN_STR "\n"
  1347. SYMBOL_NAME_STR(_maprommed) ":
  1348.     oriw    #0x0700,sr
  1349.     moveml    #0x3f20,sp@-
  1350.                 | /* Save cache settings */
  1351.     .long    0x4e7a1002    | movec cacr,d1 */
  1352.                 | /* Save MMU settings */
  1353.     .long    0x4e7a2003    | movec tc,d2
  1354.     .long    0x4e7a3004    | movec itt0,d3
  1355.     .long    0x4e7a4005    | movec itt1,d4
  1356.     .long    0x4e7a5006    | movec dtt0,d5
  1357.     .long    0x4e7a6007    | movec dtt1,d6
  1358.     moveq    #0,d0
  1359.     movel    d0,a2
  1360.                 | /* Disable caches */
  1361.     .long    0x4e7b0002    | movec d0,cacr
  1362.                 | /* Disable MMU */
  1363.     .long    0x4e7b0003    | movec d0,tc
  1364.     .long    0x4e7b0004    | movec d0,itt0
  1365.     .long    0x4e7b0005    | movec d0,itt1
  1366.     .long    0x4e7b0006    | movec d0,dtt0
  1367.     .long    0x4e7b0007    | movec d0,dtt1
  1368.     lea    0x07f80000,a0
  1369.     lea    0x00f80000,a1
  1370.     movel    a0@,d7
  1371.     cmpl    a1@,d7
  1372.     jne    1f
  1373.     movel    d7,d0
  1374.     notl    d0
  1375.     movel    d0,a0@
  1376.     nop            | /* Thanks to Jörg Mayer! */
  1377.     cmpl    a1@,d0
  1378.     jne    1f
  1379.     moveq    #-1,d0        | /* MapROMmed A3640 present */
  1380.     movel    d0,a2
  1381. 1:    movel    d7,a0@
  1382.                 | /* Restore MMU settings */
  1383.     .long    0x4e7b2003    | movec d2,tc
  1384.     .long    0x4e7b3004    | movec d3,itt0
  1385.     .long    0x4e7b4005    | movec d4,itt1
  1386.     .long    0x4e7b5006    | movec d5,dtt0
  1387.     .long    0x4e7b6007    | movec d6,dtt1
  1388.                 | /* Restore cache settings */
  1389.     .long    0x4e7b1002    | movec d1,cacr
  1390.     movel    a2,d0
  1391.     moveml    sp@+,#0x04fc
  1392.     rte
  1393. ");
  1394.  
  1395.  
  1396.     /*
  1397.      *    Reset functions for nasty Zorro boards
  1398.      */
  1399.  
  1400. static void reset_rb3(const struct ConfigDev *cd)
  1401. {
  1402.     volatile u_char *rb3_reg = (u_char *)(cd->cd_BoardAddr+0x01002000);
  1403.  
  1404.     /* FN: If a Rainbow III board is present, reset it to disable */
  1405.     /* its (possibly activated) vertical blank interrupts as the */
  1406.     /* kernel is not yet prepared to handle them (level 6). */
  1407.  
  1408.     /* set RESET bit in special function register */
  1409.     *rb3_reg = 0x01;
  1410.     /* actually, only a few cycles delay are required... */
  1411.     Sleep(1000000);
  1412.     /* clear reset bit */
  1413.     *rb3_reg = 0x00;
  1414. }
  1415.  
  1416. static void reset_piccolo(const struct ConfigDev *cd)
  1417. {
  1418.     volatile u_char *piccolo_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
  1419.  
  1420.     /* FN: the same stuff as above, for the Piccolo board. */
  1421.     /* this also has the side effect of resetting the board's */
  1422.     /* output selection logic to use the Amiga's display in single */
  1423.     /* monitor systems - which is currently what we want. */
  1424.  
  1425.     /* set RESET bit in special function register */
  1426.     *piccolo_reg = 0x01;
  1427.     /* actually, only a few cycles delay are required... */
  1428.     Sleep(1000000);
  1429.     /* clear reset bit */
  1430.     *piccolo_reg = 0x51;
  1431. }
  1432.  
  1433. static void reset_sd64(const struct ConfigDev *cd)
  1434. {
  1435.     volatile u_char *sd64_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
  1436.  
  1437.     /* FN: the same stuff as above, for the SD64 board. */
  1438.     /* just as on the Piccolo, this also resets the monitor switch */
  1439.  
  1440.     /* set RESET bit in special function register */
  1441.     *sd64_reg = 0x1f;
  1442.     /* actually, only a few cycles delay are required... */
  1443.     Sleep(1000000);
  1444.     /* clear reset bit AND switch monitor bit (0x20) */
  1445.     *sd64_reg = 0x4f;
  1446. }
  1447.  
  1448. static void reset_a2065(const struct ConfigDev *cd)
  1449. {
  1450.     volatile u_short *lance_rdp = (u_short *)(cd->cd_BoardAddr+0x4000);
  1451.     volatile u_short *lance_rap = (u_short *)(cd->cd_BoardAddr+0x4002);
  1452.  
  1453.     Disable();
  1454.  
  1455.     /* Stop the card */
  1456.     *lance_rap = 0; /* PCnet-ISA Controller Status (CSR0) */
  1457.     *lance_rdp = 4; /* STOP */
  1458.  
  1459.     Enable();
  1460. }
  1461.     
  1462. static void reset_ariadne(const struct ConfigDev *cd)
  1463. {
  1464.     volatile u_short *lance_rdp = (u_short *)(cd->cd_BoardAddr+0x0370);
  1465.     volatile u_short *lance_rap = (u_short *)(cd->cd_BoardAddr+0x0372);
  1466.     volatile u_short *lance_reset = (u_short *)(cd->cd_BoardAddr+0x0374);
  1467.  
  1468.     volatile u_char *pit_paddr = (u_char *)(cd->cd_BoardAddr+0x1004);
  1469.     volatile u_char *pit_pbddr = (u_char *)(cd->cd_BoardAddr+0x1006);
  1470.     volatile u_char *pit_pacr = (u_char *)(cd->cd_BoardAddr+0x100b);
  1471.     volatile u_char *pit_pbcr = (u_char *)(cd->cd_BoardAddr+0x100e);
  1472.     volatile u_char *pit_psr = (u_char *)(cd->cd_BoardAddr+0x101a);
  1473.  
  1474.     u_short in;
  1475.  
  1476.     Disable();
  1477.  
  1478.     /*
  1479.      *    Reset the Ethernet part (Am79C960 PCnet-ISA)
  1480.      */
  1481.  
  1482.     in = *lance_reset;   /* Reset Chip on Read Access */
  1483.     *lance_rap = 0x0000; /* PCnet-ISA Controller Status (CSR0) */
  1484.     *lance_rdp = 0x0400; /* STOP */
  1485.  
  1486.     /*
  1487.      *    Reset the Parallel part (MC68230 PI/T)
  1488.      */
  1489.  
  1490.     *pit_pacr &= 0xfd;   /* Port A Control Register */
  1491.     *pit_pbcr &= 0xfd;   /* Port B Control Register */
  1492.     *pit_psr = 0x05;     /* Port Status Register */
  1493.     *pit_paddr = 0x00;   /* Port A Data Direction Register */
  1494.     *pit_pbddr = 0x00;   /* Port B Data Direction Register */
  1495.  
  1496.     Enable();
  1497. }
  1498.  
  1499. static void reset_hydra(const struct ConfigDev *cd)
  1500. {
  1501.     volatile u_char *nic_cr  = (u_char *)(cd->cd_BoardAddr+0xffe1);
  1502.     volatile u_char *nic_isr = (u_char *)(cd->cd_BoardAddr+0xffe1 + 14);
  1503.     int n = 5000;
  1504.  
  1505.     Disable();
  1506.  
  1507.     *nic_cr = 0x21;    /* nic command register: software reset etc. */
  1508.     while (((*nic_isr & 0x80) == 0) && --n)  /* wait for reset to complete */
  1509.     ;
  1510.  
  1511.     Enable();
  1512. }
  1513.  
  1514. #if 0
  1515. static void reset_a2060(const struct ConfigDev *cd)
  1516. {
  1517. #error reset_a2060: not yet implemented
  1518. }
  1519. #endif
  1520.  
  1521.  
  1522. #ifdef ZKERNEL
  1523.  
  1524. #define    ZFILE_CHUNK_BITS    16  /* chunk is 64 KB */
  1525. #define    ZFILE_CHUNK_SIZE    (1 << ZFILE_CHUNK_BITS)
  1526. #define    ZFILE_CHUNK_MASK    (ZFILE_CHUNK_SIZE-1)
  1527. #define    ZFILE_N_CHUNKS        (2*1024*1024/ZFILE_CHUNK_SIZE)
  1528.  
  1529. /* variables for storing the uncompressed data */
  1530. static char *ZFile[ZFILE_N_CHUNKS];
  1531. static int ZFileSize = 0;
  1532. static int ZFpos = 0;
  1533. static int Zwpos = 0;
  1534.  
  1535. static int Zinfd = 0;         /* fd of compressed file */
  1536.  
  1537. /*
  1538.  * gzip declarations
  1539.  */
  1540.  
  1541. #define OF(args)  args
  1542.  
  1543. #define memzero(s, n)     memset ((s), 0, (n))
  1544.  
  1545. typedef unsigned char  uch;
  1546. typedef unsigned short ush;
  1547. typedef unsigned long  ulg;
  1548.  
  1549. #define INBUFSIZ 4096
  1550. #define WSIZE 0x8000    /* window size--must be a power of two, and */
  1551.             /*  at least 32K for zip's deflate method */
  1552.  
  1553. static uch *inbuf;
  1554. static uch *window;
  1555.  
  1556. static unsigned insize = 0;  /* valid bytes in inbuf */
  1557. static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
  1558. static unsigned outcnt = 0;  /* bytes in output buffer */
  1559. static int exit_code = 0;
  1560. static long bytes_out = 0;
  1561.  
  1562. #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  1563.         
  1564. /* Diagnostic functions (stubbed out) */
  1565. #define Assert(cond,msg)
  1566. #define Trace(x)
  1567. #define Tracev(x)
  1568. #define Tracevv(x)
  1569. #define Tracec(c,x)
  1570. #define Tracecv(c,x)
  1571.  
  1572. #define STATIC static
  1573.  
  1574. static int  fill_inbuf(void);
  1575. static void flush_window(void);
  1576. static void error(char *m);
  1577. static void gzip_mark(void **);
  1578. static void gzip_release(void **);
  1579.  
  1580. #define malloc(x)    AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
  1581. #define free(x)        FreeVec(x)
  1582.  
  1583. #ifdef LILO
  1584. #include "inflate.c"
  1585. #else
  1586. #include "../../../../lib/inflate.c"
  1587. #endif
  1588.  
  1589. static void gzip_mark(void **ptr)
  1590. {
  1591. }
  1592.  
  1593. static void gzip_release(void **ptr)
  1594. {
  1595. }
  1596.  
  1597.  
  1598. /*
  1599.  * Fill the input buffer. This is called only when the buffer is empty
  1600.  * and at least one byte is really needed.
  1601.  */
  1602. static int fill_inbuf(void)
  1603. {
  1604.     if (exit_code)
  1605.     return -1;
  1606.  
  1607.     insize = Read(Zinfd, inbuf, INBUFSIZ);
  1608.     if (insize <= 0)
  1609.     return -1;
  1610.  
  1611.     inptr = 1;
  1612.     return(inbuf[0]);
  1613. }
  1614.  
  1615. /*
  1616.  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  1617.  * (Used for the decompressed data only.)
  1618.  */
  1619. static void flush_window(void)
  1620. {
  1621.     ulg c = crc;         /* temporary variable */
  1622.     unsigned n;
  1623.     uch *in, ch;
  1624.     int chunk = Zwpos >> ZFILE_CHUNK_BITS;
  1625.  
  1626.     if (exit_code)
  1627.     return;
  1628.  
  1629.     if (chunk >= ZFILE_N_CHUNKS) {
  1630.     error("Compressed image too large! Aborting.\n");
  1631.     return;
  1632.     }
  1633.     if (!ZFile[chunk]) {
  1634.     if (!(ZFile[chunk] = (char *)AllocMem(ZFILE_CHUNK_SIZE,
  1635.                           MEMF_FAST | MEMF_PUBLIC))) {
  1636.         error("Out of memory for decompresing kernel image\n");
  1637.         return;
  1638.     }
  1639.     }
  1640.     memcpy(ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt);
  1641.     Zwpos += outcnt;
  1642.     
  1643. #define    DISPLAY_BITS 10
  1644.     if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0)
  1645.     PutChar('.');
  1646.     
  1647.     in = window;
  1648.     for (n = 0; n < outcnt; n++) {
  1649.     ch = *in++;
  1650.     c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  1651.     }
  1652.     crc = c;
  1653.     bytes_out += (ulg)outcnt;
  1654.     outcnt = 0;
  1655. }
  1656.  
  1657. static void error(char *x)
  1658. {
  1659.     Printf("\n%s", x);
  1660.     exit_code = 1;
  1661. }
  1662.  
  1663. static inline int call_sub(int (*func)(void), void *stackp)
  1664. {
  1665.     register int _res __asm("d0");
  1666.     register int (*a0)(void) __asm("a0") = func;
  1667.     register int (*a1)(void) __asm("a1") = stackp;
  1668.  
  1669.     __asm __volatile ("movel sp,a2;"
  1670.                   "movel a1,sp;"
  1671.                   "jsr a0@;"
  1672.                   "movel a2,sp"
  1673.               : "=r" (_res)
  1674.               : "r" (a0), "r" (a1)
  1675.               : "a0", "a1", "a2", "d0", "d1", "memory");
  1676.     return(_res);
  1677. }
  1678.  
  1679. static int load_zkernel(int fd)
  1680. {
  1681.     int i, err = -1;
  1682. #define ZSTACKSIZE    (16384)
  1683.     u_long *zstack;
  1684.     
  1685.     for (i = 0; i < ZFILE_N_CHUNKS; ++i)
  1686.     ZFile[i] = NULL;
  1687.     Zinfd = fd;
  1688.     Seek(fd, 0);
  1689.     
  1690.     if (!(inbuf = (uch *)AllocMem(INBUFSIZ, MEMF_FAST | MEMF_PUBLIC)))
  1691.     Puts("Couldn't allocate gunzip buffer\n");
  1692.     else {
  1693.     if (!(window = (uch *)AllocMem(WSIZE, MEMF_FAST | MEMF_PUBLIC)))
  1694.         Puts("Couldn't allocate gunzip window\n");
  1695.     else {
  1696.         if (!(zstack = (u_long *)AllocMem(ZSTACKSIZE,
  1697.                               MEMF_FAST | MEMF_PUBLIC)))
  1698.         Puts("Couldn't allocate gunzip stack\n");
  1699.         else {
  1700.         Puts("Uncompressing kernel image ");
  1701.         makecrc();
  1702.         if (!(err = call_sub(gunzip, (char *)zstack+ZSTACKSIZE)))
  1703.             Puts("done\n");
  1704.         ZFileSize = Zwpos;
  1705.         FreeMem(zstack, ZSTACKSIZE);
  1706.         }
  1707.         FreeMem(window, WSIZE);
  1708.         window = NULL;
  1709.     }
  1710.     FreeMem(inbuf, INBUFSIZ);
  1711.     inbuf = NULL;
  1712.     }
  1713.     Close(Zinfd);    /* input file not needed anymore */
  1714.     return(err);
  1715. }
  1716.  
  1717.  
  1718. /* Note about the read/lseek wrapper and its memory management: It assumes
  1719.  * that all seeks are only forward, and thus data already read or skipped can
  1720.  * be freed. This is true for current organization of bootstrap and kernels.
  1721.  * Little exception: The struct kexec at the start of the file. After reading
  1722.  * it, there may be a seek back to the end of the file. But this currently
  1723.  * doesn't hurt. (Roman)
  1724.  */
  1725.  
  1726. static int KRead(int fd, void *buf, int cnt)
  1727. {
  1728.     unsigned done = 0;
  1729.     
  1730.     if (!ZFileSize)
  1731.     return(Read(fd, buf, cnt));
  1732.     
  1733.     if (ZFpos + cnt > ZFileSize)
  1734.     cnt = ZFileSize - ZFpos;
  1735.     
  1736.     while (cnt > 0) {
  1737.     unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
  1738.     unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
  1739.     unsigned n = cnt;
  1740.  
  1741.     if (ZFpos + n > endchunk)
  1742.         n = endchunk - ZFpos;
  1743.     memcpy(buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n);
  1744.     cnt -= n;
  1745.     buf += n;
  1746.     done += n;
  1747.     ZFpos += n;
  1748.  
  1749.     if (ZFpos == endchunk) {
  1750.         FreeMem(ZFile[chunk], ZFILE_CHUNK_SIZE);
  1751.         ZFile[chunk] = NULL;
  1752.     }
  1753.     }
  1754.  
  1755.     return(done);
  1756. }
  1757.  
  1758.  
  1759. static int KSeek(int fd, int offset)
  1760. {
  1761.     unsigned oldpos, oldchunk, newchunk;
  1762.  
  1763.     if (!ZFileSize)
  1764.     return(Seek(fd, offset));
  1765.  
  1766.     oldpos = ZFpos;
  1767.     ZFpos = offset;
  1768.     if (ZFpos < 0) {
  1769.     ZFpos = 0;
  1770.     return(-1);
  1771.     } else if (ZFpos > ZFileSize) {
  1772.     ZFpos = ZFileSize;
  1773.     return(-1);
  1774.     }
  1775.  
  1776.     /* free memory of skipped-over data */
  1777.     oldchunk = oldpos >> ZFILE_CHUNK_BITS;
  1778.     newchunk = ZFpos  >> ZFILE_CHUNK_BITS;
  1779.     while(oldchunk < newchunk) {
  1780.     if (ZFile[oldchunk]) {
  1781.         FreeMem(ZFile[oldchunk], ZFILE_CHUNK_SIZE);
  1782.         ZFile[oldchunk] = NULL;
  1783.     }
  1784.     ++oldchunk;
  1785.     }
  1786.     return(ZFpos);
  1787. }
  1788.  
  1789.  
  1790. static void free_zfile(void)
  1791. {
  1792.     int i;
  1793.  
  1794.     for (i = 0; i < ZFILE_N_CHUNKS; ++i)
  1795.     if (ZFile[i]) {
  1796.         FreeMem(ZFile[i], ZFILE_CHUNK_SIZE);
  1797.         ZFile[i] = NULL;
  1798.     }
  1799. }
  1800.  
  1801. static int KClose(int fd)
  1802. {
  1803.     if (ZFileSize) {
  1804.     free_zfile();
  1805.     ZFileSize = 0;
  1806.     } else
  1807.     Close(fd);
  1808.     return(0);
  1809. }
  1810. #endif /* ZKERNEL */
  1811.